package com.diu.domain.strategy.service.armory;

import com.diu.domain.strategy.model.entity.StrategyAwardEntity;
import com.diu.domain.strategy.model.entity.StrategyEntity;
import com.diu.domain.strategy.model.entity.StrategyRuleEntity;
import com.diu.domain.strategy.repository.IStrategyRepository;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author diu
 * @description 策略装配，随机抽奖
 * @create_time 2025/10/4 12:25
 */
@Service
public class StrategyArmoryDispatch implements IStrategyDispatch, IStrategyArmory {
    @Resource
    private IStrategyRepository repository;

    @Override
    public boolean assembleLotteryWeightStrategy(Long strategyId) {
        List<StrategyAwardEntity> strategyAwardEntities = repository.queryStrategyAwardList(strategyId);

        StrategyEntity strategyEntity = repository.queryStrategyByStrategyId(strategyId);
        if(strategyEntity == null) return false;
        String strategyWeight = strategyEntity.getRuleWeight();
        StrategyRuleEntity strategyRuleEntity = new StrategyRuleEntity();
        if (strategyWeight == null || strategyWeight.length() == 0){
            strategyRuleEntity = repository.queryStrategyRuleByStrategyId(strategyId);
        }else{
            strategyRuleEntity = repository.queryStrategyRuleByStrategyIdAndRuleModel(strategyId, strategyWeight);
        }
        if(strategyRuleEntity == null) return false;
        Map<String, List<Integer>> strategyRuleWeight = strategyRuleEntity.getRuleValueMap();
        // 装配不同ruleWeight的抽奖策略
        for (Map.Entry<String, List<Integer>> entry : strategyRuleWeight.entrySet()) {
            String ruleWeight = entry.getKey();
            List<Integer> awardIdList = entry.getValue();
            List<StrategyAwardEntity> awardEntities = new ArrayList<>();
            for(Integer awardId : awardIdList){
                StrategyAwardEntity tempStrategyAwardEntity = repository.queryStrategyAwardListByStrategyAndAwardId(strategyId, awardId);
                if(tempStrategyAwardEntity == null) continue;
                awardEntities.add(tempStrategyAwardEntity);
            }
            assembleLotteryStrategy(ruleWeight, awardEntities);
        }
        return true;
    }
    
    @Override
    public boolean assembleLotteryStrategy(String key, List<StrategyAwardEntity> strategyAwardEntities) {
        // 1. 初始化策略奖品概率查找表
        BigDecimal totalRate = strategyAwardEntities.stream()
                .map(StrategyAwardEntity::getAwardRate)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        // 忽略概率总和不为100%的情况
        // 2. 初始化策略奖品概率查找表
        BigDecimal currentRate = BigDecimal.ZERO;
        Map<BigDecimal, Integer> map = new HashMap<>();
        for (StrategyAwardEntity strategyAwardEntity : strategyAwardEntities) {
            currentRate = currentRate.add(strategyAwardEntity.getAwardRate());
            map.put(currentRate, strategyAwardEntity.getAwardId());
        }
        repository.storeStrategyAwardSearchRateTableOwn(key, map.size(), map, totalRate);
        return true;
    }

    @Override
    public boolean assembleLotteryStrategy(Long strategyId) {
        List<StrategyAwardEntity> strategyAwardEntities = repository.queryStrategyAwardList(strategyId);
        return assembleLotteryStrategy(strategyId+"", strategyAwardEntities);
    }

    @Override
    public Integer getRandomAwardId(Long strategyId) {
        BigDecimal totalRate = repository.getRateRange(strategyId+"");
        if(totalRate.compareTo(BigDecimal.ZERO) == 0){
            throw new IllegalArgumentException("策略装配未完成，请先装配策略");
        }
        BigDecimal rateRange = BigDecimal.valueOf(new SecureRandom().nextDouble()).multiply(totalRate);
        // 通过生成的随机值，获取概率值奖品查找表的结果
        return repository.getStrategyAwardAssembleOwn(strategyId+"", rateRange);
    }

    @Override
    public Integer getRandomAwardId(Long strategyId, String key) {
        // 分布式部署下，不一定为当前应用做的策略装配。也就是值不一定会保存到本应用，而是分布式应用，所以需要从 Redis 中获取。
        BigDecimal totalRate = repository.getRateRange(strategyId+"_"+key);
        if(totalRate.compareTo(BigDecimal.ZERO) == 0){
            throw new IllegalArgumentException("策略装配未完成，请先装配策略");
        }
        BigDecimal rateRange = BigDecimal.valueOf(new SecureRandom().nextDouble()).multiply(totalRate);
        // 通过生成的随机值，获取概率值奖品查找表的结果
        return repository.getStrategyAwardAssembleOwn(strategyId+"_"+key, rateRange);
    }
}
